import { View, Text } from '@tarojs/components';
import { useState, useEffect } from 'react';
import './snakeGame.scss';
import Taro,{ useDidShow, useReady, useRouter } from '@tarojs/taro';

class SnakePart{
  constructor(front, x, y) {
    this.front = front
    this.x = x
    this.y = y
  }
  move () {
    // 跟随前面的零件移动
    this.x = this.front.x
    this.y = this.front.y
  }
}
class Head{
  constructor(direction, x, y) {
    this.direction = direction || 0
    this.x = x
    this.y = y
  }
  move(){
    // 检查其当前方向并相应移动
    if (this.direction == 0) {
      // 向左
      this.x += 1
    } else if (this.direction == 1) {
      // 向上
      this.y += 1
    } else if (this.direction == 2) {
      // 向左
      this.x -= 1
    } else if (this.direction == 3) {
      // 向下
      this.y -= 1
    } 
  }
}
let rand = (function () {
  var today = new Date();
  var seed = today.getTime();
  function rnd() {
    seed = (seed * 9301 + 49297) % 233280;
    return seed / 233280.0;
  }
  return function rand(number) {
    return Math.round(rnd(seed) * number);
  };
})();
class SnakeGame{
  constructor(opts) {
    this.opts = opts || {
      success: () => {}
    };
    this.timer = null // 计时器
    this.CELL_SIZE = 20 // 棋盘游戏中每个单元格的大小
    this.BOARD_SIZE = 45 // 游戏中沿宽度方向的单元格数
    this.SPEED = 12 // 改变速度，让比赛进行得更快
    this.GROWTH = 3 // 吃了一个苹果后，蛇会以生长单位生长
    this.eaten = true // 跟踪是否吃了苹果的变量
    this.quit = false // 用于检查游戏是否应该退出的变量
    this.isGameOver = false // 游戏是否结束
    this.grow = 0 // 跟踪增长的变量
    this.snake = [] // 储存蛇的阵列
    this.board = [] // 棋盘
    this.subx = 0 // 增长x模块坐标
    this.suby = 0 // 增长y模块坐标
    this.applex = 0 // 苹果的x坐标
    this.appley = 0 // 苹果的y坐标
    this.head = new Head(0, parseInt((this.BOARD_SIZE - 1) / 2), parseInt((this.BOARD_SIZE - 1) / 2)) // 蛇头从板的中心开始
    // 将蛇头存放到蛇的列表中
    this.snake.push(this.head)
    this.createBoard()
    // 创建棋盘
    this.init()
  }
  // 创建棋盘
  createBoard () {
    for (let i = 0; i < this.BOARD_SIZE; i++){
      this.board[i] = [];
      for (let j = 0; j < this.BOARD_SIZE; j++){
        this.board[i][j] = {
          color: `rgb(0,0,0)`,
          y: i,
          x: j
        }
      }
    }
  }
  createSanke () {
    // 把蛇染成绿色
    this.board.flat(1).forEach(item => item.color = `rgb(0,0,0)`)
    console.log(this.snake)
    this.snake.forEach(item => {
      console.log(item)
      this.board[item.y][item.x].color = `rgb(0,255,0)`;
    })
    console.log(`this.appley,this.applex`,this.appley,this.applex)
    this.board[this.appley][this.applex].color = `rgb(0,0,255)`;
  }
  createApple () {
    // 检查苹果是否被吃掉并产生一个新的
    if (this.eaten) {
      // 创建所有可能位置的列表
      // 删除作为蛇的一部分的单元格
      let s = this.board.reduce((prev, acc) => {
        return [...prev,...acc]
      }, []).filter(item => {
        let emptys = this.snake.filter(snake => {
          if (snake.x == item.x && snake.y == item.y) {
            return snake;
          }
        })
        if (emptys.length == 0) {
          return item;
        }
      })
      console.log('s',s)
      // 从剩余单元格中随机选取
      let a = rand(s.length - 1)
      console.log('a',a)
      // // 苹果红色
      s[a].color = `rgb(0,0,255)`;
      this.applex = s[a].x;
      this.appley = s[a].y;
      this.eaten = false
    }
  }
  // 更新方向
  updateDirection (direction = 0) {
    // 0 向右
    // 1 向下
    // 2 向左
    // 3 向上
    this.head.direction = direction;
    console.log(this.head)
  }
  // 移动蛇
  movingSnake () {
    for (let i = this.snake.length - 1; i >= 0; i--){
      this.snake[i].move()
    }
  }
  // 碰撞规则
  collisionRules () {
    // 游戏结束
    if (this.head.x < 0 || this.head.x > this.BOARD_SIZE - 1 || this.head.y < 0 || this.head.y > this.BOARD_SIZE - 1) {
      this.isGameOver = true;
    }
    for (let i = 1; i < this.snake.length; i++) { 
      let part = this.snake[i]
      if (this.head.x == part.x && this.head.y == part.y) {
        this.quit = true
        this.isGameOver = true
      }
    }
    if (this.quit) {
      this.isGameOver = true
    }
  }
  // 蛇在多个画面上逐渐生长
  addSnake () {
    if(this.grow > 0){
      this.snake.push(new SnakePart(this.snake[this.snake.length - 1], this.subx, this.suby))
      this.grow -= 1
    }
  }
  // 蛇吃苹果就会长大
  growSnake () {
    if(this.applex == this.head.x && this.appley == this.head.y){
      this.subx = this.snake[this.snake.length - 1].x
      this.suby = this.snake[this.snake.length - 1].y
      this.eaten = true
      this.grow += this.GROWTH
    }
  }
  init () {
    // this.createBoard()
    this.createApple()
    this.createSanke()
    this.movingSnake()
    this.collisionRules()
    this.addSnake()
    this.growSnake()
  }
  run () {
    this.opts.success && this.opts.success(this.board)
    if (this.isGameOver && this.timer) {
      clearTimeout(this.timer)
      this.isGameOver = false
      this.timer = null
      return;
    } else {
      this.init()
      this.timer = setTimeout(() => {
        this.run();
      },parseInt(1000/this.SPEED))
    }
  }
}

const SnakeGamePage = (props) => {
  // 运行
  let [board, setBoard] = useState([])
  let [snakes,setSnakes] = useState({})
  useDidShow(() => {
    let snake = new SnakeGame({
      success(board){
        setBoard([...board])
      }
    })
    setBoard(snake.board)
    setSnakes(snake)
  })
  function startGame () {
    snakes.run()
  }
  function changeDirection (num = 0) {
    console.log(num)
    snakes.updateDirection(num)
  }
  return <View className='rui-snake-game-page-content'>
    <View>
      {
        board.map((item, idx) => <View className='rui-flex-ac' key={idx}>{
          item && item.map((cur, i) => <View
            style={`background:${cur.color};`}
            className='rui-board-li' key={cur.x + cur.y + i}></View>)
        }</View>)
      }
    </View>
    <View className='rui-flex-ac'>
      {/* // 0 向右
      // 1 向下
      // 2 向左
      // 3 向上 */}
      <View className='rui-de-btn' onClick={changeDirection.bind(null,3)}>上</View>
      <View className='rui-de-btn' onClick={changeDirection.bind(null,1)}>下</View>
      <View className='rui-de-btn' onClick={changeDirection.bind(null,2)}>左</View>
      <View className='rui-de-btn' onClick={changeDirection.bind(null,0)}>右</View>
    </View>
    <View onClick={startGame}>开始</View>
  </View>
}
export default SnakeGamePage;